<template>
  <el-container class="fm2-container">
    <el-main class="fm2-main">
      <el-container>
        <el-container class="center-container" direction="vertical">
          <el-header class="btn-bar" style="height: 45px;">
            <slot name="action"></slot>
            <el-button
              type="text"
              size="medium"
              icon="el-icon-upload2"
              :disabled="true"
            >{{$t('bpmn.actions.import')}}</el-button>
            <el-button
              type="text"
              size="medium"
              icon="el-icon-download"
              @click="handleExportXmlAction"
            >{{$t('bpmn.actions.importXml')}}</el-button>
            <el-button
              type="text"
              size="medium"
              icon="el-icon-download"
              @click="handleExportSvgAction"
            >{{$t('bpmn.actions.importSvg')}}</el-button>
            <el-button
              type="text"
              size="medium"
              icon="el-icon-tickets"
              @click="showXMLCode"
            >{{$t('bpmn.actions.preview')}}</el-button>
            <el-button
              type="text"
              size="medium"
              icon="el-icon-delete"
              @click="resetDiagram"
            >{{$t('bpmn.actions.clear')}}</el-button>
            <el-button type="text" size="medium" icon="el-icon-document">{{$t('bpmn.actions.save')}}</el-button>
          </el-header>
          <el-main>
            <div class="containers" :style="{height: getContainerHeight}">
              <div class="canvas" ref="canvas" />

              <el-dialog :visible.sync="xmlVisible" title="XML" :fullscreen="false" top="10vh">
                <vue-ace-editor
                  v-model="process.xml"
                  @init="editorInit"
                  lang="xml"
                  theme="chrome"
                  width="100%"
                  height="400"
                  :options="{wrap: true, readOnly: true}"
                ></vue-ace-editor>
                <span slot="footer" class="dialog-footer">
                  <el-button
                    icon="el-icon-document"
                    v-clipboard:copy="process.xml"
                    v-clipboard:success="onCopy"
                  >复 制</el-button>
                  <el-button icon="el-icon-close" type="primary" @click="xmlVisible = false">关闭</el-button>
                </span>
              </el-dialog>
            </div>
          </el-main>
        </el-container>

        <el-aside class="widget-config-container">
          <el-container>
            <el-header height="45px">
              <div
                class="config-tab"
                :class="{active: configTab=='node'}"
                @click="handleConfigSelect('node')"
              >节点属性</div>
              <div
                class="config-tab"
                :class="{active: configTab=='process'}"
                @click="handleConfigSelect('process')"
              >流程属性</div>
            </el-header>
            <el-main class="config-content">
              <node-property-panel v-if="bpmnModeler && configTab=='node'" :modeler="bpmnModeler" />
              <process-property-panel
                v-if="bpmnModeler && process.element && configTab=='process'"
                :element="process.element"
                :modeler="bpmnModeler"
              ></process-property-panel>
            </el-main>
          </el-container>
        </el-aside>
      </el-container>
    </el-main>
    <el-footer height="30px" style="font-weight: 600;">
      Powered by
      <a
        target="_blank"
        href="https://gitee.com/xiaofanger/vue-bpmn-flowable"
      >vue-bpmn-flowable</a>
    </el-footer>
  </el-container>
</template>

<script>
// bpmn-js 设计器
import BpmnModeler from "bpmn-js/lib/Modeler";
// 对flowable的扩展
import flowableExtensionModule from "jp-flowable-bpmn-moddle/lib";
import flowableModdle from "jp-flowable-bpmn-moddle/resources/flowable";

import NodePropertyPanel from "./NodePropertyPanel"; // 属性面板
import ProcessPropertyPanel from "./ProcessPropertyPanel";

import BpmData from "./BpmData";
import VueAceEditor from "vue2-ace-editor";

export default {
  props: {
    processName: {
      type: String,
      default: "流程1567044459787",
    },
    processKey: {
      type: String,
      default: "process1567044459787",
    },
    processDescription: {
      type: String,
      default: "描述",
    },
  },

  components: {
    NodePropertyPanel,
    ProcessPropertyPanel,
    VueAceEditor,
  },

  data() {
    return {
      bpmnModeler: null,
      process_data: {
        name: this.processName,
        id: this.processKey,
        description: this.processDescription,
      },
      process: {
        element: null,
        xml: "",
        svg: "",
      },
      configTab: "process",
      nodeProcessSelect: null,

      xmlVisible: false,
      element: null,
      bpmData: new BpmData(),
    };
  },

  methods: {
    /**
     * bind SVG element height.
     */
    getContainerHeight() {
      return document.body.offsetHeight - 75 + "px";
    },
    /**
     * init ace editor.
     */
    editorInit: function () {
      require("brace/ext/language_tools"); //language extension prerequsite...
      require("brace/mode/xml"); //language
      require("brace/theme/chrome");
    },
    resetDiagram(init = false) {
      if (!init) this.bpmnModeler.clear();
      this.bpmnModeler.createDiagram();
      setTimeout(() => {
        let re = this.bpmnModeler.get("elementRegistry");
        this.process.element = re.get("Process_1");
        const modeling = this.bpmnModeler.get("modeling");
        modeling.updateProperties(this.process.element, this.process_data);
      }, 300);
    },

    // 调整左侧工具栏排版
    adjustPalette() {
      debugger;
      try {
        // 获取 bpmn 设计器实例
        const canvas = this.$refs.canvas;
        const djsPalette = canvas.children[0].children[1].children[4];
        const djsPalStyle = {
          width: "130px",
          padding: "5px",
          background: "white",
          left: "20px",
          borderRadius: 0,
        };
        for (var key in djsPalStyle) {
          djsPalette.style[key] = djsPalStyle[key];
        }
        const palette = djsPalette.children[0];
        const allGroups = palette.children;
        allGroups[0].style["display"] = "none";
        // 修改控件样式
        for (var gKey in allGroups) {
          const group = allGroups[gKey];
          for (var cKey in group.children) {
            const control = group.children[cKey];
            const controlStyle = {
              display: "flex",
              justifyContent: "flex-start",
              alignItems: "center",
              width: "100%",
              padding: "5px",
            };
            if (
              control.className &&
              control.dataset &&
              control.className.indexOf("entry") !== -1
            ) {
              const controlProps = this.bpmData.getControl(
                control.dataset.action
              );
              control.innerHTML = `<div style='font-size: 14px;font-weight:500;margin-left:15px;'>${controlProps["title"]}</div>`;
              if (controlProps["tooltip"]) {
                control.title = controlProps["tooltip"];
              }
              for (var csKey in controlStyle) {
                control.style[csKey] = controlStyle[csKey];
              }
            }
          }
        }
      } catch (e) {
        console.log(e);
      }
    },

    // 当图发生改变的时候会调用这个函数，这个data就是图的xml
    setEncoded(type, data) {
      // 把xml转换为URI，下载要用到的
      const encodedData = encodeURIComponent(data);
      if (data) {
        if (type === "XML") {
          // 获取到图的xml，保存就是把这个xml提交给后台
          this.process.xml = data;
          return {
            filename: this.process.name + ".xml",
            href: "data:application/bpmn20-xml;charset=UTF-8," + encodedData,
            data: data,
          };
        }
        if (type === "SVG") {
          this.process.svg = data;
          return {
            filename: this.process.name + ".svg",
            href: "data:application/text/xml;charset=UTF-8," + encodedData,
            data: data,
          };
        }
      }
    },
    /**
     * 导出BPMN XML文件
     */
    handleExportXmlAction() {
      const _this = this;
      this.bpmnModeler.saveXML({ format: true }, function (err, xml) {
        if (err) {
          console.error(err);
        }
        let { filename, href } = _this.setEncoded("XML", xml);
        if (href && filename) {
          let a = document.createElement("a");
          a.download = filename; //指定下载的文件名
          a.href = href; //  URL对象
          a.click(); // 模拟点击
          URL.revokeObjectURL(a.href); // 释放URL 对象
        }
      });
    },
    /**
     * 导出BPMN SVG文件
     */
    handleExportSvgAction() {
      const _this = this;
      this.bpmnModeler.saveSVG(function (err, svg) {
        if (err) {
          console.error(err);
        }
        let { filename, href } = _this.setEncoded("SVG", svg);
        if (href && filename) {
          let a = document.createElement("a");
          a.download = filename;
          a.href = href;
          a.click();
          URL.revokeObjectURL(a.href);
        }
      });
    },
    showXMLCode() {
      const _this = this;
      this.bpmnModeler.saveXML({ format: true }, function (err, xml) {
        if (err) {
          console.error(err);
          return;
        }
        _this.process.xml = xml;
        _this.xmlVisible = !_this.xmlVisible;
      });
    },
    /**
     * 复制内容到剪切板成功回调
     */
    onCopy() {
      this.$message.success("内容复制成功");
    },
    /**
     * 配置Tab切换
     */
    handleConfigSelect(value) {
      this.configTab = value;
    },
  },

  mounted() {
    const canvas = this.$refs.canvas;
    // 生成实例
    this.bpmnModeler = new BpmnModeler({
      container: canvas,
      additionalModules: [flowableExtensionModule],
      moddleExtensions: {
        flowable: flowableModdle,
      },
    });

    this.resetDiagram(true);
  },
};
</script>

<style lang="scss">
/*左边工具栏以及编辑节点的样式*/
@import "~bpmn-js/dist/assets/diagram-js.css";
@import "~bpmn-js/dist/assets/bpmn-font/css/bpmn.css";
@import "~bpmn-js/dist/assets/bpmn-font/css/bpmn-codes.css";
@import "~bpmn-js/dist/assets/bpmn-font/css/bpmn-embedded.css";
.containers {
  /*position: absolute;*/
  background-color: #ffffff;
  width: 100%;
  height: 100%;

  .canvas {
    width: 100%;
    height: 100%;
  }
  .panel {
    position: absolute;
    right: 0;
    top: 50px;
    width: 300px;
  }
  .bjs-powered-by {
    display: none;
  }
  .toolbar {
    position: absolute;
    top: 0;
    right: 320px;
    height: 40px;
    width: 600px;
    border: 1px solid red;
    a {
      text-decoration: none;
      margin: 5px;
      color: #409eff;
    }
  }
}
</style>
